// depends on "primitive_datatypes.h"

#pragma once 

struct Vec2{
	union {
		struct{
			Number x;
			Number y;
		};
		struct{
			Number _x;
			Number _y;
		};
		Number _data[2];
	};
	// constructors
	Vec2();						// default ctor
	Vec2(Number xy);			// 
	Vec2(Int xy);				// 
	Vec2(Number x,Number y);	// 
	Vec2(Int x, Int y);			// 
	Vec2(const Vec2& old);		// 
	Vec2& operator = (Const Vec2& old);
	
	// assignment operators
    Vec2&	operator += ( Const Vec2& other);
    Vec2&	operator -= ( Const Vec2& other);
    Vec2&	operator *= ( Number scalar);
    Vec2&	operator *= ( Int scalar);
	Vec2&	operator /= ( Number scalar);

	// unary operators
    Vec2	operator + () Const;
    Vec2	operator - () Const;

	// binary operators
    Vec2	operator + ( Const Vec2& other) Const;
    Vec2	operator - ( Const Vec2& other) Const;
    Number	operator * ( Const Vec2& other) Const;
	Vec2	operator * ( Number scalar)		Const;
	Vec2	operator * ( Int scalar)		Const;
    Vec2	operator / ( Number scalar)		Const;
	Vec2	operator / ( Int scalar)		Const;

    friend Vec2 operator * ( Number scalar, Const Vec2& vec);
	friend Vec2 operator * ( Int scalar, Const Vec2& vec);

    Bool	operator == ( Const Vec2& other) Const;
    Bool	operator != ( Const Vec2& other) Const;

	// normal member functions

	Number	length		(void) Const;
	Number	sqrLength	(void) Const;
	Vec2&	normalize	(void);
	Vec2	normalized	(void) Const;
	Vec2&	negate		(void);
	Vec2	negated		(void) Const;
	Vec2&	truncate	(Number max);
	Vec2	truncated	(Number max) Const;
	Number	distance	(Const Vec2& other) Const;
	Number	dotProduct	(Const Vec2& other) Const;
	Number	cosine		(Const Vec2& other) Const;
	Number	angle		(Const Vec2& other) Const;
	

	// static functions
	static Vec2  EmptyVector(void)					{ return Vec2(0,0); }
	static Vec2  UnitVector(Const Number units = 1)	{ return Vec2(units,units); }
	static Vec2  Up(void)							{ return Vec2(0,1); }
	static Vec2	 Right(void)						{ return Vec2(1,0); }
	static Vec2  Down(void)							{ return Vec2(0,-1); }
	static Vec2  Left(void)							{ return Vec2(-1,0); }
	static Vec2  MaxVec(Const Vec2& vec1,Const Vec2 vec2);
	static Vec2  MinVec(Const Vec2& vec1,Const Vec2 vec2);
	static Vec2  Reflect(Const Vec2& vSource,Const Vec2& vNormal);
	static Vec2  Lerp(Const Vec2& vFrom,Const Vec2& vTo,Number fPercentage);
	static Vec2  CatmullRom(Const Vec2& vP0,Const Vec2& vP1,Const Vec2& vP2,Const Vec2& vP3,Number fPercentage);

};

struct Vec3{
	union {
		struct{
			Number x;
			Number y;
			Number z;
		};
		struct{
			Number _x;
			Number _y;
			Number _z;
		};
		Number _data[3];
	};

	// constructors
	Vec3();								// default ctor
	Vec3(Number xyz);					// 
	Vec3(Int xyz);						// 
	Vec3(Number x,Number y,Number z);	// 
	Vec3(Int x, Int y,int z);			// 
	Vec3(Const Vec3& old);				// 
	Vec3& operator = (Const Vec3& old);
	
	// assignment operators
    Vec3&	operator += ( Const Vec3& other);
    Vec3&	operator -= ( Const Vec3& other);
    Vec3&	operator *= ( Number scalar);
    Vec3&	operator *= ( Int scalar);
	Vec3&	operator /= ( Number scalar);

	// unary operators
    Vec3	operator + () Const;
    Vec3	operator - () Const;

	// binary operators
    Vec3	operator + ( Const Vec3& other) Const;
    Vec3	operator - ( Const Vec3& other) Const;
    Number	operator * ( Const Vec3& other) Const;
	Vec3	operator * ( Number scalar)		Const;
	Vec3	operator * ( Int scalar)		Const;
    Vec3	operator / ( Number scalar)		Const;
	Vec3	operator / ( Int scalar)		Const;

    friend Vec3 operator * ( Number scalar, Const Vec3& vec);
	friend Vec3 operator * ( Int scalar, Const Vec3& vec);

    Bool	operator == ( Const Vec3& other) Const;
    Bool	operator != ( Const Vec3& other) Const;

	// normal member functions
	Number	length		(void) Const;
	Number	sqrLength	(void) Const;
	Vec3&	normalize	(void);
	Vec3	normalized	(void) Const;
	Vec3&	negate		(void);
	Vec3	negated		(void) Const;
	Vec3&	truncate	(Number max);
	Vec3	truncated	(Number max) Const;
	Number	distance	(Const Vec3& other) Const;
	Number	dotProduct	(Const Vec3& other) Const;
	Vec3	crossProduct(Const Vec3& other) Const;
	Number	cosine		(Const Vec3& other) Const;
	Number	angle		(Const Vec3& other) Const;
	

	// static functions
	static Vec3  EmptyVector(void)					{ return Vec3(0,0,0); }
	static Vec3  UnitVector(Const Number units = 1)	{ return Vec3(units,units,units); }
	static Vec3  Up(void)							{ return Vec3(0,1,0); }
	static Vec3	 Right(void)						{ return Vec3(1,0,0); }
	static Vec3  Down(void)							{ return Vec3(0,-1,0); }
	static Vec3  Left(void)							{ return Vec3(-1,0,0); }
	static Vec3  Forward(void)						{ return Vec3(0,0,1); }
	static Vec3  Backwards(void)					{ return Vec3(0,0,-1); }
	static Vec3  MaxVec(Const Vec3& vec1,Const Vec3 vec2);
	static Vec3  MinVec(Const Vec3& vec1,Const Vec3 vec2);
	static Vec3  Reflect(Const Vec3& vSource,Const Vec3& vNormal);
	static Vec3  Lerp(Const Vec3& vFrom,Const Vec3& vTo,Number fPercentage);
	static Vec3  CatmullRom(Const Vec3& vP0,Const Vec3& vP1,Const Vec3& vP2,Const Vec3& vP3,Number fPercentage);

};

struct Vec4{
	union {
		struct{
			Number x;
			Number y;
			Number z;
			Number w;
		};
		struct{
			Number _x;
			Number _y;
			Number _z;
			Number _w;
		};
		Number _data[4];
	};

	// constructors
	Vec4();								// default ctor
	Vec4(Number xyzw);					// 
	Vec4(Int xyzw);						//
	Vec4(Number xyz,Number w);
	Vec4(Int xyz,Int w);
	Vec4(Number x,Number y,Number z,Number w);	// 
	Vec4(Int x, Int y,Int z,Int w);			// 
	Vec4(Const Vec3& old,Number w = 1.0f);				// 
	Vec4(Const Vec4& old);
	Vec4& operator= (Const Vec3& old);
	Vec4& operator= (Const Vec4& old);

	// assignment operators
	Vec4&	operator += ( Const Vec4& other);
    Vec4&	operator -= ( Const Vec4& other);
    Vec4&	operator *= ( Number scalar);
    Vec4&	operator *= ( Int scalar);
	Vec4&	operator /= ( Number scalar);

	// unary operators
    Vec4	operator + () Const;
    Vec4	operator - () Const;

	// binary operators
    Vec4	operator + ( Const Vec4& other) Const;
    Vec4	operator - ( Const Vec4& other) Const;
    Number	operator * ( Const Vec4& other) Const;
	Vec4	operator * ( Number scalar)		Const;
	Vec4	operator * ( Int scalar)		Const;
    Vec4	operator / ( Number scalar)		Const;
	Vec4	operator / ( Int scalar)		Const;

    friend Vec4 operator * ( Number scalar, Const Vec4& vec);
	friend Vec4 operator * ( Int scalar, Const Vec4& vec);

    Bool	operator == ( Const Vec4& other) Const;
    Bool	operator != ( Const Vec4& other) Const;

	// normal member functions
	Number	length		(void) Const;
	Number	sqrLength	(void) Const;
	Vec4&	normalize	(void);
	Vec4	normalized	(void) Const;
	Vec4&	negate		(void);
	Vec4	negated		(void) Const;
	Vec4&	truncate	(Number max);
	Vec4	truncated	(Number max) Const;
	Number	distance	(Const Vec4& other) Const;
	Number	dotProduct	(Const Vec4& other) Const;
	Vec4	crossProduct(Const Vec4& other) Const;
	Number	cosine		(Const Vec4& other) Const;
	Number	angle		(Const Vec4& other) Const;

	// static functions
	static Vec4  EmptyVector(void)					{ return Vec4(0,0,0,1); }
	static Vec4  UnitVector(Const Number units = 1)	{ return Vec4(units,units,units,units); }
	static Vec4  Up(void)							{ return Vec4(0,1,0,0); }
	static Vec4	 Right(void)						{ return Vec4(1,0,0,0); }
	static Vec4  Down(void)							{ return Vec4(0,-1,0,0); }
	static Vec4  Left(void)							{ return Vec4(-1,0,0,0); }
	static Vec4  Forward(void)						{ return Vec4(0,0,1,0); }
	static Vec4  Backwards(void)					{ return Vec4(0,0,-1,0); }
	static Vec4  MaxVec(Const Vec4& vec1,Const Vec4 vec2);
	static Vec4  MinVec(Const Vec4& vec1,Const Vec4 vec2);
	static Vec4  Reflect(Const Vec4& vSource,Const Vec4& vNormal);
	static Vec4  Lerp(Const Vec4& vFrom,Const Vec4& vTo,Number fPercentage);
	static Vec4  CatmullRom(Const Vec4& vP0,Const Vec4& vP1,Const Vec4& vP2,Const Vec4& vP3,Number fPercentage);
};